#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "minimapeditdialog.h"
#include <QFileDialog>
#include <QProcess>
#include <QDesktopServices>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->menuBar->hide();

    ui->mainToolBar->removeAction(ui->actionSave_As);

    ui->propInfoTextEdit->setText("<h1>No prop selected</h1>");

    setDeviceSaveEnabled(false);

    contextMenu = new QMenu;
    contextMenu->addAction("New Prop", this, SLOT(on_actionNew_Prop_triggered()));
    contextMenu->addSeparator();
    contextMenu->addAction("Edit Prop", this, SLOT(editPropTriggered()));
    contextMenu->addAction("Remove Prop", this, SLOT(removePropTriggered()));

    xmlInt = new XMLInterface;
    connect(xmlInt, SIGNAL(propAdded(PropData*, bool)), this, SLOT(addProp(PropData*, bool)));
    connect(xmlInt, SIGNAL(propRemoved(QString)), this, SLOT(removeProp(QString)));
    connect(xmlInt, SIGNAL(propRemovedXmlOnly(QString)), this, SLOT(removePropXmlOnly(QString)));
    connect(xmlInt, SIGNAL(minimapAdded(PropData*, bool)), this, SLOT(addMinimap(PropData*, bool)));

    localInt = new LocalInterface(xmlInt);
    connect(localInt, SIGNAL(logMessage(QString,MESSAGE_TYPE)), this, SLOT(addToLog(QString,MESSAGE_TYPE)));

    mtpInt = new MTPInterface(xmlInt, localInt, this);
    connect(this, SIGNAL(pushDataToDevice()), mtpInt, SLOT(pushData()));
    connect(mtpInt, SIGNAL(logMessage(QString,MESSAGE_TYPE)), this, SLOT(addToLog(QString,MESSAGE_TYPE)));
    connect(mtpInt, SIGNAL(copyInProgress(bool)), this, SLOT(lockInterface(bool)));
    connect(mtpInt, SIGNAL(deviceConnect(bool)), this, SLOT(setDeviceSaveEnabled(bool)));
    connect(xmlInt, SIGNAL(propAudioScriptRequest(PropData*)), mtpInt, SLOT(setPropAudioScriptFromDevice(PropData*)));

    if (xmlInt->getMinimap() == 0)
    {
        // default map is disaster city
        PropData *map = new PropData;
        map->propCoords[0].latitude = 30.578690;
        map->propCoords[0].longitude = -96.352486;
        map->propCoords[1].latitude = 30.573969;
        map->propCoords[1].longitude = -96.349092;
        std::vector<QString> p;
        p.push_back(QCoreApplication::applicationDirPath() + "/disastercity_map.png");
        map->addPic(p);
        map->changePropName("Minimap");
        addMinimap(map);
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::lockInterface(bool lock)
{
    this->setEnabled(!lock);
    on_xmlListWidget_itemSelectionChanged();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    mtpInt->closeMtpCopy();
    event->accept();
}

void MainWindow::addToLog(QString message, MESSAGE_TYPE mtype)
{
    switch (mtype)
    {
    case INFO:
        ui->logTextEdit->append(message);
        break;
    case IMPORTANT:
        ui->logTextEdit->append("<b>" + message + "</b>");
        break;
    case ERROR:
        ui->logTextEdit->append("<font color=\"#ff0000\"><b>" + message + "</b></font>");
        break;
    case STATUS:
        // don't display status messages
    default:
        break;
    }
}

void MainWindow::setDeviceSaveEnabled(bool enabled)
{
    ui->actionSave_to_Device->setEnabled(enabled);
    ui->actionNew_Prop->setEnabled(enabled);
    ui->actionSave_As->setEnabled(enabled);
    // maybe should let user sync instead so it is easier to use multiple devices
    xmlInt->removeDeviceProps();
    //ui->actionEdit_Minimap->setEnabled(enabled);
}

/**
  User clicked new prop button/menu
  */
void MainWindow::on_actionNew_Prop_triggered()
{
    PropEditDialog ped(this);
    connect(&ped,
            SIGNAL(newPropInfo(PropData*)),
            this,
            SLOT(addProp(PropData*)));
    ped.exec();
}

/**
  User clicked edit prop button
  */
void MainWindow::editPropTriggered()
{
    QListWidgetItem *selItem = ui->xmlListWidget->selectedItems()[0];
    if (selItem->text() == "Minimap")
    {
        PropData *prop = xmlInt->getMinimap();
        MiniMapEditDialog mmed(prop);
        if (mmed.exec() == QDialog::Accepted)
        {
            editProp(prop, selItem);
        }
    }
    else
    {
        PropData *prop = xmlInt->getPropByName(selItem->text());
        PropEditDialog ped(this, prop);
        if (ped.exec() == QDialog::Accepted)
        {
            editProp(prop, selItem);
        }
    }
}

/**
  User clicked remove prop button
  */
void MainWindow::removePropTriggered()
{
    QListWidgetItem *selItem = ui->xmlListWidget->selectedItems()[0];
    if (selItem->text() == "Minimap")
        return;
    xmlInt->removePropByName(selItem->text());
    mtpInt->deleteProp(selItem->text(), true);
    localInt->removePropFolder(selItem->text());
    localInt->updatePaths();
    ui->xmlListWidget->removeItemWidget(selItem);
    delete selItem;
}

void MainWindow::removeProp(QString pName)
{
    if (pName != "Minimap")
    {
        xmlInt->removePropByName(pName);
    }
    else
    {
        return;
        //xmlInt->clearMinimap();
    }
    mtpInt->deleteProp(pName, true);
    localInt->removePropFolder(pName);
    localInt->updatePaths();
    QListWidgetItem *selItem = ui->xmlListWidget->findItems(pName, Qt::MatchFixedString)[0];
    ui->xmlListWidget->removeItemWidget(selItem);
    delete selItem;
}

void MainWindow::removePropXmlOnly(QString name)
{
    QListWidgetItem *selItem = ui->xmlListWidget->findItems(name, Qt::MatchFixedString)[0];
    if (selItem != NULL)
    {
        ui->xmlListWidget->removeItemWidget(selItem);
        delete selItem;
    }
}

/**
  Updates the main QTreeWidget with new prop data and adds the prop.
  PropData *prop - the prop to add
  */
void MainWindow::addProp(PropData *prop, bool updateLocal)
{
    xmlInt->addProp(prop);
    if (updateLocal)
    {
        localInt->updatePaths();
    }
    new QListWidgetItem(prop->getPropName(), ui->xmlListWidget);
}

/**
  Updates prop information on the main QListWidget
  PropData *prop - The new prop info
  QListWidgetItem *item - The QListWidgetItem to update.
  */
void MainWindow::editProp(PropData *prop, QListWidgetItem *item)
{
    if (item->text() != prop->getPropName())
    {
        //localInt->removePropFolder(item->text());
        mtpInt->renameProp(item->text(), prop->getPropName());
        item->setText(prop->getPropName());
    }
    localInt->updatePaths();
    // Reload prop info in the second pane
    on_xmlListWidget_itemSelectionChanged();
}

void MainWindow::on_actionSave_to_Device_triggered()
{
    emit pushDataToDevice();
}

void MainWindow::on_actionSave_As_triggered()
{
    QString path = QFileDialog::getSaveFileName(this, "Save As", QString(), "XML file (*.xml)");
    if (path == "")
        return;
    if (!path.endsWith(".xml", Qt::CaseInsensitive))
        path.append(".xml");
    xmlInt->buildXML(path);
}

bool MainWindow::propExists(QString pName)
{
    if (xmlInt->getPropByName(pName) == 0)
        return false;
    else
        return true;
}

void MainWindow::on_xmlListWidget_customContextMenuRequested(const QPoint &pos)
{
    QList<QAction *> actions = contextMenu->actions();
    if (ui->xmlListWidget->itemAt(pos) == 0)
    {
        actions[2]->setEnabled(false);
        actions[3]->setEnabled(false);
    }
    else
    {
        actions[2]->setEnabled(true);
        actions[3]->setEnabled(true);
        if (ui->xmlListWidget->itemAt(pos)->text() == "Minimap")
        {
            actions[3]->setEnabled(false);
        }
    }
    QPoint lwPt = ui->xmlListWidget->pos();
    QPoint menuPos = QWidget::mapToGlobal(pos);
    menuPos.setX(menuPos.x() + lwPt.x());
    menuPos.setY(menuPos.y() + lwPt.y());
    menuPos.setY(menuPos.y() + ui->mainToolBar->height());
    contextMenu->popup(menuPos);
}

void MainWindow::on_xmlListWidget_itemSelectionChanged()
{
    QList<QListWidgetItem *> selected = ui->xmlListWidget->selectedItems();
    if (selected.size() == 0)
    {
        ui->propInfoTextEdit->setText("<h1>No prop selected</h1>");
        return;
    }

    // only one can be selected at once
    QListWidgetItem *selItem = selected[0];
    PropData *curProp;
    if (selItem->text() == "Minimap")
    {
        curProp = xmlInt->getMinimap();
    }
    else
    {
        curProp = xmlInt->getPropByName(selItem->text());
    }
    QString text = "";

    text += "<html>\n<body>\n<h1>" + curProp->getPropName() + "</h1>";
    /*switch (curProp->propStatus)
    {
    case PROP_SAVED:
        text += "<font color=\"#00ff00\"><b>Saved to device!</b></font><br />";
        break;
    case PROP_NOT_SAVED:
        text += "<font color=\"#ff0000\"><b>Not saved to device!</b></font><br />";
        break;
    }*/

    if (curProp->getPropName() != "Minimap")
    {
        text += "<b>Coordinates:</b><table cellpadding=\"2\"><tr><td>Latitude</td><td>Longitude</td><td>Altitude</td><td>Radius</td></tr>";
        text += "<tr><td>" + QString::number(curProp->propCoords[0].latitude, 'f', 6) + "</td>" +
                "<td>" + QString::number(curProp->propCoords[0].longitude, 'f', 6) + "</td>" +
                "<td>" + QString::number(curProp->propCoords[0].altitude, 'f', 6) + "</td>" +
                "<td>" + QString::number(curProp->propCoords[0].radius, 'f', 6) + "</td></tr>";
        text += "</table></br>";

        /*text += "<b>Main Audio:</b> ";
        if (curProp->getAudMain()->first != "")
        {
            text += curProp->getAudMain()->first + "<br />";
        }
        else
        {
            text += "(no main audio)<br />";
        }
        text += "<b>Main Audio Script:</b> ";
        QString amscr = curProp->getAudMainScript()->first;
        if (amscr != "")
        {
            amscr.replace("\n", "<br />");
            text += "<br />" + amscr + "<br />";
        }
        else
        {
            text += "(no main audio script)<br />";
        }*/

        text += "<b>Audio:</b> ";
        if (curProp->aud.size() > 0)
        {
            text += "<ul>";
            for (unsigned int k = 0; k < curProp->aud.size(); k++)
            {
                text += "<li>" + curProp->aud[k]->first + "</li>";
            }
            text += "</ul>";
        }
        else
        {
            text += "(no additional audio)<br />";
        }

        text += "<b>Video:</b>: ";
        if (curProp->vid.size() > 0)
        {
            text += "<ul>";
            for (unsigned int k = 0; k < curProp->vid.size(); k++)
            {
                text += "<li>" + curProp->vid[k]->first + "</li>";
            }
            text += "</ul>";
        }
        else
        {
            text += "(no additional video)<br />";
        }

        text += "<b>Pictures:</b> ";
        if (curProp->pic.size() > 0)
        {
            text += "<ul>";
            for (unsigned int k = 0; k < curProp->pic.size(); k++)
            {
                text += "<li>" + curProp->pic[k]->first;
                QFileInfo finfo(curProp->pic[k]->first);
                if (!finfo.exists())
                {
                    finfo.setFile(curProp->pic[k]->first + ".lnk");
                    text += QString("<br />") + "<img src=\"" + finfo.symLinkTarget() + "\" width=\"150\" />";
                }
                else
                {
                    text += QString("<br />") + "<img src=\"" + curProp->pic[k]->first + "\" width=\"150\" />";
                }
                text += "</li>";
            }
            text += "</ul>";
        }
        else
        {
            text += "(no additional pictures)<br />";
        }
    }
    else
    {
        // minimap
        text += "<b>Coordinates:</b><table cellpadding=\"2\"><tr><td></td><td>Latitude</td><td>Longitude</td></tr>";
        for (unsigned int k = 0; k < 2; k++) // only 2 coords for minimap
        {
            // only care about lat/lon
            text += "<tr><td>" + QString::number(k+1) + "</td>" +
                    "<td>" + QString::number(curProp->propCoords[k].latitude, 'f', 6) + "</td>" +
                    "<td>" + QString::number(curProp->propCoords[k].longitude, 'f', 6) + "</td></tr>";
        }
        text += "</table></br>";
        text += "<b>Minimap image:</b> ";
        QString pic = curProp->pic[0]->first;
        text += pic + "<br />";
        QFileInfo finfo(pic);
        if (!finfo.exists())
        {
            finfo.setFile(pic + ".lnk");
            text += "<img src=\"" + finfo.symLinkTarget() + "\" width=\"150\" />";
        }
        else
        {
            text += "<img src=\"" + pic + "\" width=\"150\" />";
        }
    }
    text += "</body></html>";

    ui->propInfoTextEdit->setText(text);
}

void MainWindow::on_xmlListWidget_itemDoubleClicked(QListWidgetItem *item)
{
    if (item->text() == "Minimap")
    {
        PropData *prop = xmlInt->getMinimap();
        MiniMapEditDialog mmed(prop);
        if (mmed.exec() == QDialog::Accepted)
        {
            editProp(prop, item);
        }
    }
    else
    {
        PropData *prop = xmlInt->getPropByName(item->text());
        if (prop == 0)
        {
            addToLog("Couldn't find prop. This should never happen. Yell at the programmer", ERROR);
            return;
        }
        PropEditDialog ped(this, prop);
        if (ped.exec() == QDialog::Accepted)
        {
            editProp(prop, item);
        }
    }
}

void MainWindow::addMinimap(PropData *prop, bool updateLocal)
{
    xmlInt->setMinimap(prop);
    if (updateLocal)
    {
        localInt->updatePaths();
    }
    new QListWidgetItem(prop->getPropName(), ui->xmlListWidget);
}

void MainWindow::on_actionEdit_Minimap_triggered()
{
    // minimapeditdialog
    PropData *mmap = xmlInt->getMinimap();
    if (mmap == 0)
    {
        MiniMapEditDialog mmed;
        connect(&mmed, SIGNAL(newMinimapInfo(PropData*)), this, SLOT(addMinimap(PropData*)));
        mmed.exec();
    }
    else
    {
        QListWidgetItem *item = ui->xmlListWidget->findItems("Minimap", Qt::MatchFixedString)[0];
        MiniMapEditDialog mmed(mmap);
        if (mmed.exec() == QDialog::Accepted)
        {
            editProp(mmap, item);
        }
    }
}

PropData * MainWindow::getMinimapData()
{
    return xmlInt->getMinimap();
}
